package io.github.loserYa.log;

import com.alibaba.fastjson2.JSONObject;
import io.github.loserYa.log.handler.ShardingHandler;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * sql 构建 处理类
 *
 * @author loser
 * @date 2024/4/25
 */
public class SqlBuildHandler implements ApplicationContextAware {

    private final Map<String, ShardingHandler> SHARDING_MAP = new ConcurrentHashMap<>();

    public List<String> buildSql(JSONObject entity) {

        String table = EntitySqlParser.convertToUnderscore(entity.remove(LogConstant.TABLE).toString());
        Object dataList = entity.remove(LogConstant.LIST);
        Object update = entity.remove(LogConstant.UPDATE);
        if (Objects.nonNull(dataList)) {
            ArrayList<JSONObject> array = (ArrayList<JSONObject>) dataList;
            List<SqlBuild> sqlList = new ArrayList<>(array.size());
            for (JSONObject jsonObject : array) {
                sqlList.add(EntitySqlParser.generateInsertSQL(jsonObject, table, SHARDING_MAP.get(table)));
            }
            return mergeSql(sqlList);
        } else if (Objects.nonNull(update)) {
            return Collections.singletonList(EntitySqlParser.generateUpdateSQL(entity, (JSONObject) update, table, SHARDING_MAP.get(table)).buildUpdate());
        } else {
            return Collections.singletonList(EntitySqlParser.generateInsertSQL(entity, table, SHARDING_MAP.get(table)).buildInsert());
        }

    }

    private List<String> mergeSql(List<SqlBuild> sqlList) {

        List<String> list = new ArrayList<>();
        Map<String, List<SqlBuild>> map = sqlList.stream().filter(SqlBuild::notNull).collect(Collectors.groupingBy(SqlBuild::uniqueKey));
        for (Map.Entry<String, List<SqlBuild>> entry : map.entrySet()) {
            SqlBuild sqlBuild = entry.getValue().get(0);
            String values = entry.getValue().stream().map(SqlBuild::getValues).collect(Collectors.joining(","));
            String sql = SqlBuild.buildInsert(sqlBuild.getTableName(), sqlBuild.getColumns(), values).buildInsert();
            list.add(sql);
        }
        return list;

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, ShardingHandler> shardingHandlers = applicationContext.getBeansOfType(ShardingHandler.class);
        if (CollectionUtils.isEmpty(shardingHandlers)) {
            return;
        }
        for (ShardingHandler shardingHandler : shardingHandlers.values()) {
            SHARDING_MAP.put(shardingHandler.table(), shardingHandler);
        }
    }
}
